package com.xuan.bazi.core;

import com.nlf.calendar.Lunar;
import com.nlf.calendar.Solar;

import java.util.*;

/**
 * 八字工具
 *
 * @author kty
 */
public class BaZiUtil {

    /**
     * ☆判断日期类型并返回农历日期、公历日期
     *
     * @param setting 八字设置
     * @return 日期
     */
    public static Map<String, Object> isDateType(BaZiSetting setting) {

        Date date = setting.getDate(); // 日期
        int dateType = setting.getDateType(); // 日期类型（0:公历，1:农历）

        Lunar lunar = null; // 农历日期
        Solar solar = null; // 公历日期
        Map<String, Object> map = new HashMap<>(); // 存放公历日期和农历日期

        // 2、按公历日期计算
        if (dateType == BaZiEnum.DATE_TYPE_SOLAR.getMark()) {
            // 2.1、通过公历日期初始化
            lunar = new Lunar(date); // 农历日期
            solar = lunar.getSolar(); // 公历日期
        }

        // 3、按农历日期计算
        if (dateType == BaZiEnum.DATE_TYPE_LUNAR.getMark()) {
            // 3.1、通过日期获取年月日时分秒
            Calendar c = Calendar.getInstance();
            c.setTime(date);
            int year = c.get(Calendar.YEAR); // 年
            int month = c.get(Calendar.MONTH) + 1; // 月
            int day = c.get(Calendar.DATE); // 日
            int hour = c.get(Calendar.HOUR_OF_DAY); // 时
            int minute = c.get(Calendar.MINUTE); // 分
            int second = c.get(Calendar.SECOND); // 秒
            // 3.2、通过农历年月日时分秒初始化
            lunar = new Lunar(year, month, day, hour, minute, second); // 农历日期
            solar = lunar.getSolar(); // 公历日期
        }

        // 4、设置日期
        assert null != lunar && null != solar;
        map.put("lunar", lunar); // 设置农历日期
        map.put("solar", lunar.getSolar()); // 设置公历日期
        map.put("lunarStr", lunarStr(lunar)); // 将Lunar型农历日期转为String型农历日期（格式：二〇〇年一月初一子时）
        map.put("solarStr", solarStr(solar)); // 将Solar型公历日期转为String型公历日期（格式：yyyy年M月d日HH时mm分ss秒）

        return map;

    }

    /**
     * ☆判断四柱设置并返回八字
     *
     * @param setting 八字设置
     */
    public static List<String> isSiZhu(BaZiSetting setting, Lunar lunar) {

        int yearZhuSet = setting.getYearZhuSet(); // 年柱设置（0:以正月初一作为新年的开始，1：以立春当天作为新年的开始，2：以立春交接的时刻作为新年的开始）
        int monthZhuSet = setting.getMonthZhuSet(); // 月柱设置（0:以节交接当天起算，1：以节交接时刻起算）
        int ziShiLiuPai = setting.getZiShiLiuPai(); // 子时流派（0:晚子时日干支算当天，1：晚子时日干支算明天）
        int hourZhuSet = setting.getHourZhuSet(); // 时柱设置（0:支持早子时和晚子时）

        List<String> list = new ArrayList<>();

        // 1、判断年柱设置
        if (yearZhuSet == BaZiEnum.YEAR_ZHU_SET_CHUYI.getMark()) {
            list.add(lunar.getYearInGanZhi()); // 以正月初一作为新年的开始
        } else if (yearZhuSet == BaZiEnum.YEAR_ZHU_SET_LICHUN_DAY.getMark()) {
            list.add(lunar.getYearInGanZhiByLiChun()); // 以立春当天作为新年的开始
        } else if (yearZhuSet == BaZiEnum.YEAR_ZHU_SET_LICHUN_SHIKE.getMark()) {
            list.add(lunar.getYearInGanZhiExact()); // 以立春交接的时刻作为新年的开始
        } else {
            list.add(lunar.getYearInGanZhi()); // 默认；以正月初一作为新年的开始
        }

        // 2、判断月柱设置
        if (monthZhuSet == BaZiEnum.MONTH_ZHU_SET_DAY.getMark()) {
            list.add(lunar.getMonthInGanZhi()); // 以节交接当天起算
        } else if (monthZhuSet == BaZiEnum.MONTH_ZHU_SET_SHIKE.getMark()) {
            list.add(lunar.getMonthInGanZhiExact()); // 以节交接时刻起算
        } else {
            list.add(lunar.getMonthInGanZhi()); // 默认；以节交接当天起算
        }

        // 3、判断日柱设置（用子时流派判断）
        if (ziShiLiuPai == BaZiEnum.ZI_SHI_LIU_PAI_TOMORROW.getMark()) {
            list.add(lunar.getDayInGanZhiExact()); // 晚子时日柱算明天
        } else if (ziShiLiuPai == BaZiEnum.ZI_SHI_LIU_PAI_TODAY.getMark()) {
            list.add(lunar.getDayInGanZhiExact2()); // 晚子时日柱算当天
        } else {
            list.add(lunar.getDayInGanZhiExact()); // 默认；晚子时日柱算明天
        }

        // 4、判断时柱设置
        if (hourZhuSet == BaZiEnum.HOUR_ZHU_SET.getMark()) {
            list.add(lunar.getTimeInGanZhi()); // 支持早子时和晚子时
        } else {
            list.add(lunar.getTimeInGanZhi()); // 默认；支持早子时和晚子时
        }

        // 5、返回八字
        return list;

    }

//----------------------------------------------------------------------------------------------------------------------------------------------------

    /**
     * 将Solar型公历日期转为String型公历日期（转换后格式：yyyy年MM月dd日HH时mm分ss秒）
     *
     * @param solar 公历日期
     * @return String型公历日期
     */
    private static String solarStr(Solar solar) {

        return (solar.getYear() + "年" + solar.getMonth() + "月" +
                solar.getDay() + "日" + solar.getHour() + "时" +
                solar.getMinute() + "分" + solar.getSecond() + "秒");

    }

    /**
     * 将Lunar型农历日期转为String型农历日期（转换后格式：二〇〇年一月初一子时）
     */
    private static String lunarStr(Lunar lunar) {

        // 获取小时
        int hour = lunar.getHour();

        String lunarStr;

        // 判断时辰
        if (hour >= 23 || hour < 1) {
            // 判断早晚子时
            if (hour >= 23) {
                lunarStr = lunar + "(晚)子时";
            } else {
                lunarStr = lunar + "(早)子时";
            }
        } else {
            lunarStr = lunar + BaZiMap.HOUR_ZHI.get(hour) + "时";
        }

        return lunarStr;

    }


}
